let

  generic =
    # utils
    {
      stdenv,
      fetchFromGitHub,
      fetchurl,
      fetchpatch2,
      lib,
      replaceVars,
      writeShellScriptBin,

      # source specification
      hash,
      muslPatches ? { },
      rev,
      version,

      # runtime dependencies
      darwin,
      freebsd,
      glibc,
      libuuid,
      libxml2,
      lz4,
      openssl,
      readline,
      tzdata,
      zlib,
      zstd,

      # build dependencies
      bison,
      docbook-xsl-nons,
      docbook_xml_dtd_45,
      flex,
      libxslt,
      makeBinaryWrapper,
      pkg-config,
      removeReferencesTo,

      # passthru
      buildEnv,
      buildPackages,
      newScope,
      nixosTests,
      postgresqlTestHook,
      self,
      stdenvNoCC,
      testers,

      # Block size
      # Changing the block size will break on-disk database compatibility. See:
      # https://www.postgresql.org/docs/current/install-make.html#CONFIGURE-OPTION-WITH-BLOCKSIZE
      withBlocksize ? null,
      withWalBlocksize ? null,

      # bonjour
      bonjourSupport ? false,

      # Curl
      curlSupport ?
        lib.versionAtLeast version "18"
        && lib.meta.availableOn stdenv.hostPlatform curl
        # Building statically fails with:
        # configure: error: library 'curl' does not provide curl_multi_init
        # https://www.postgresql.org/message-id/487dacec-6d8d-46c0-a36f-d5b8c81a56f1%40technowledgy.de
        && !stdenv.hostPlatform.isStatic,
      curl,

      # GSSAPI
      gssSupport ? with stdenv.hostPlatform; !isWindows && !isStatic,
      libkrb5,

      # icu
      # Building with icu in pkgsStatic gives tons of "undefined reference" errors like this:
      #   /nix/store/452lkaak37d3mzzn3p9ak7aa3wzhdqaj-icu4c-74.2-x86_64-unknown-linux-musl/lib/libicuuc.a(chariter.ao):
      #    (.data.rel.ro._ZTIN6icu_7417CharacterIteratorE[_ZTIN6icu_7417CharacterIteratorE]+0x0):
      #    undefined reference to `vtable for __cxxabiv1::__si_class_type_info'
      icuSupport ? !stdenv.hostPlatform.isStatic,
      icu,

      # JIT
      jitSupport ?
        stdenv.hostPlatform.canExecute stdenv.buildPlatform
        # Building with JIT in pkgsStatic fails like this:
        #   fatal error: 'stdio.h' file not found
        && !stdenv.hostPlatform.isStatic,
      llvmPackages_20,
      nukeReferences,
      overrideCC,

      # LDAP
      ldapSupport ? false,
      openldap,

      # NLS
      nlsSupport ? false,
      gettext,

      # NUMA
      numaSupport ? lib.versionAtLeast version "18" && lib.meta.availableOn stdenv.hostPlatform numactl,
      numactl,

      # PAM
      pamSupport ?
        lib.meta.availableOn stdenv.hostPlatform linux-pam
        # Building with linux-pam in pkgsStatic gives a few "undefined reference" errors like this:
        #   /nix/store/3s55icpsbc36sgn7sa8q3qq4z6al6rlr-linux-pam-static-x86_64-unknown-linux-musl-1.6.1/lib/libpam.a(pam_audit.o):
        #     in function `pam_modutil_audit_write':(.text+0x571):
        #     undefined reference to `audit_close'
        && !stdenv.hostPlatform.isStatic,
      linux-pam,

      # PL/Perl
      perlSupport ?
        lib.meta.availableOn stdenv.hostPlatform perl
        # Building with perl in pkgsStatic gives this error:
        #   configure: error: cannot build PL/Perl because libperl is not a shared library
        && !stdenv.hostPlatform.isStatic
        # configure tries to call the perl executable for the version
        && stdenv.buildPlatform.canExecute stdenv.hostPlatform,
      perl,

      # PL/Python
      pythonSupport ?
        lib.meta.availableOn stdenv.hostPlatform python3
        # Building with python in pkgsStatic gives this error:
        #  checking how to link an embedded Python application... configure: error: could not find shared library for Python
        && !stdenv.hostPlatform.isStatic
        # configure tries to call the python executable
        && stdenv.buildPlatform.canExecute stdenv.hostPlatform,
      python3,

      # PL/Tcl
      tclSupport ?
        lib.meta.availableOn stdenv.hostPlatform tcl
        # tcl is broken in pkgsStatic
        && !stdenv.hostPlatform.isStatic
        # configure fails with:
        #   configure: error: file 'tclConfig.sh' is required for Tcl
        && stdenv.buildPlatform.canExecute stdenv.hostPlatform,
      tcl,

      # SELinux
      selinuxSupport ? false,
      libselinux,

      # Systemd
      systemdSupport ? lib.meta.availableOn stdenv.hostPlatform systemdLibs,
      systemdLibs,

      # Uring
      uringSupport ? lib.versionAtLeast version "18" && lib.meta.availableOn stdenv.hostPlatform liburing,
      liburing,
    }@args:
    let
      atLeast = lib.versionAtLeast version;
      olderThan = lib.versionOlder version;
      lz4Enabled = atLeast "14";
      zstdEnabled = atLeast "15";

      dlSuffix = if olderThan "16" then ".so" else stdenv.hostPlatform.extensions.sharedLibrary;

      # Pin LLVM 20 until upstream has fully resolved:
      # https://www.postgresql.org/message-id/flat/d25e6e4a-d1b4-84d3-2f8a-6c45b975f53d%40applied-asynchrony.com
      # Currently still a problem on aarch64.
      # TODO: Remove with next minor releases
      llvmPackages = lib.warnIf (
        version == "17.8"
      ) "PostgreSQL: Is the pin for LLVM 20 still needed?" llvmPackages_20;

      stdenv' =
        if !stdenv.cc.isClang then
          overrideCC llvmPackages.stdenv (
            llvmPackages.stdenv.cc.override {
              # LLVM bintools are not used by default, but are needed to make -flto work below.
              bintools = llvmPackages.bintools;
            }
          )
        else
          stdenv;
    in
    stdenv'.mkDerivation (finalAttrs: {
      inherit version;
      pname = "postgresql";

      src = fetchFromGitHub {
        owner = "postgres";
        repo = "postgres";
        # rev, not tag, on purpose: allows updating when new versions
        # are "stamped" a few days before release (tag).
        inherit hash rev;
      };

      __structuredAttrs = true;

      outputs = [
        "out"
        "dev"
        "doc"
        "lib"
        "man"
      ]
      ++ lib.optionals jitSupport [ "jit" ]
      ++ lib.optionals perlSupport [ "plperl" ]
      ++ lib.optionals pythonSupport [ "plpython3" ]
      ++ lib.optionals tclSupport [ "pltcl" ];

      outputChecks = {
        out = {
          disallowedReferences = [
            "dev"
            "doc"
            "man"
          ]
          ++ lib.optionals jitSupport [ "jit" ];
          disallowedRequisites = [
            stdenv'.cc
            llvmPackages.llvm.out
            llvmPackages.llvm.lib
          ]
          ++ (map lib.getDev (builtins.filter (drv: drv ? "dev") finalAttrs.buildInputs));
        };

        lib = {
          disallowedReferences = [
            "out"
            "dev"
            "doc"
            "man"
          ]
          ++ lib.optionals jitSupport [ "jit" ];
          disallowedRequisites = [
            stdenv'.cc
            llvmPackages.llvm.out
            llvmPackages.llvm.lib
          ]
          ++ (map lib.getDev (builtins.filter (drv: drv ? "dev") finalAttrs.buildInputs));
        };

        doc = {
          disallowedReferences = [
            "out"
            "dev"
            "man"
          ]
          ++ lib.optionals jitSupport [ "jit" ];
        };

        man = {
          disallowedReferences = [
            "out"
            "dev"
            "doc"
          ]
          ++ lib.optionals jitSupport [ "jit" ];
        };
      }
      // lib.optionalAttrs jitSupport {
        jit = {
          disallowedReferences = [
            "dev"
            "doc"
            "man"
          ];
          disallowedRequisites = [
            stdenv'.cc
            llvmPackages.llvm.out
          ]
          ++ (map lib.getDev (builtins.filter (drv: drv ? "dev") finalAttrs.buildInputs));
        };
      };

      strictDeps = true;

      buildInputs = [
        zlib
        readline
        openssl
        libxml2
        libuuid
      ]
      ++ lib.optionals icuSupport [ icu ]
      ++ lib.optionals jitSupport [ llvmPackages.llvm ]
      ++ lib.optionals lz4Enabled [ lz4 ]
      ++ lib.optionals zstdEnabled [ zstd ]
      ++ lib.optionals systemdSupport [ systemdLibs ]
      ++ lib.optionals uringSupport [ liburing ]
      ++ lib.optionals curlSupport [ curl ]
      ++ lib.optionals numaSupport [ numactl ]
      ++ lib.optionals gssSupport [ libkrb5 ]
      ++ lib.optionals pamSupport [ linux-pam ]
      ++ lib.optionals perlSupport [ perl ]
      ++ lib.optionals ldapSupport [ openldap ]
      ++ lib.optionals selinuxSupport [ libselinux ]
      ++ lib.optionals nlsSupport [ gettext ];

      nativeBuildInputs = [
        bison
        docbook-xsl-nons
        docbook_xml_dtd_45
        flex
        libxml2
        libxslt
        makeBinaryWrapper
        perl
        pkg-config
        removeReferencesTo
      ]
      ++ lib.optionals jitSupport [
        llvmPackages.llvm.dev
        nukeReferences
      ];

      enableParallelBuilding = true;

      separateDebugInfo = true;

      buildFlags = [ "world" ];

      env = {
        # libpgcommon.a and libpgport.a contain all paths returned by pg_config and are linked
        # into all binaries. However, almost no binaries actually use those paths. The following
        # flags will remove unused sections from all shared libraries and binaries - including
        # those paths. This avoids a lot of circular dependency problems with different outputs,
        # and allows splitting them cleanly.
        CFLAGS = "-fdata-sections -ffunction-sections -flto";

        # This flag was introduced upstream in:
        # https://github.com/postgres/postgres/commit/b6c7cfac88c47a9194d76f3d074129da3c46545a
        # It causes errors when linking against libpq.a in pkgsStatic:
        #   undefined reference to `pg_encoding_to_char'
        # Unsetting the flag fixes it. The upstream reasoning to introduce it is about the risk
        # to have initdb load a libpq.so from a different major version and how to avoid that.
        # This doesn't apply to us with Nix.
        NIX_CFLAGS_COMPILE = "-UUSE_PRIVATE_ENCODING_FUNCS";
      }
      // lib.optionalAttrs perlSupport { PERL = lib.getExe perl; }
      // lib.optionalAttrs pythonSupport { PYTHON = lib.getExe python3; }
      // lib.optionalAttrs tclSupport { TCLSH = "${lib.getBin tcl}/bin/tclsh"; };

      configureFlags =
        let
          inherit (lib) withFeature;
        in
        [
          "--with-openssl"
          "--with-libxml"
          (withFeature icuSupport "icu")
          "--sysconfdir=/etc"
          "--with-system-tzdata=${tzdata}/share/zoneinfo"
          "--enable-debug"
          (lib.optionalString systemdSupport "--with-systemd")
          (if stdenv.hostPlatform.isFreeBSD then "--with-uuid=bsd" else "--with-uuid=e2fs")
          (withFeature perlSupport "perl")
        ]
        ++ lib.optionals (withBlocksize != null) [ "--with-blocksize=${toString withBlocksize}" ]
        ++ lib.optionals (withWalBlocksize != null) [ "--with-wal-blocksize=${toString withWalBlocksize}" ]
        ++ lib.optionals lz4Enabled [ "--with-lz4" ]
        ++ lib.optionals zstdEnabled [ "--with-zstd" ]
        ++ lib.optionals uringSupport [ "--with-liburing" ]
        ++ lib.optionals curlSupport [ "--with-libcurl" ]
        ++ lib.optionals numaSupport [ "--with-libnuma" ]
        ++ lib.optionals gssSupport [ "--with-gssapi" ]
        ++ lib.optionals pythonSupport [ "--with-python" ]
        ++ lib.optionals jitSupport [ "--with-llvm" ]
        ++ lib.optionals pamSupport [ "--with-pam" ]
        # This can be removed once v17 is removed. v18+ ships with it.
        ++ lib.optionals (stdenv'.hostPlatform.isDarwin && atLeast "16" && olderThan "18") [
          "LDFLAGS_EX_BE=-Wl,-export_dynamic"
        ]
        # some version of this flag is required in all cross configurations
        # since it cannot be automatically detected
        ++
          lib.optionals
            (
              (!stdenv'.hostPlatform.isDarwin)
              && (!(stdenv'.buildPlatform.canExecute stdenv.hostPlatform))
              && atLeast "16"
            )
            [
              "LDFLAGS_EX_BE=-Wl,--export-dynamic"
            ]
        ++ lib.optionals ldapSupport [ "--with-ldap" ]
        ++ lib.optionals tclSupport [ "--with-tcl" ]
        ++ lib.optionals selinuxSupport [ "--with-selinux" ]
        ++ lib.optionals nlsSupport [ "--enable-nls" ]
        ++ lib.optionals bonjourSupport [ "--with-bonjour" ];

      patches = [
        (
          if atLeast "16" then
            ./patches/relative-to-symlinks-16+.patch
          else
            ./patches/relative-to-symlinks.patch
        )
        (
          if atLeast "15" then
            ./patches/empty-pg-config-view-15+.patch
          else
            ./patches/empty-pg-config-view.patch
        )
        ./patches/less-is-more.patch
        ./patches/paths-for-split-outputs.patch
        ./patches/paths-with-postgresql-suffix.patch

        (replaceVars ./patches/locale-binary-path.patch {
          locale = "${
            if stdenv.hostPlatform.isDarwin then
              darwin.adv_cmds
            else if stdenv.hostPlatform.isFreeBSD then
              freebsd.locale
            else
              lib.getBin stdenv.cc.libc
          }/bin/locale";
        })
      ]
      ++ lib.optionals stdenv'.hostPlatform.isMusl (
        # Using fetchurl instead of fetchpatch on purpose: https://github.com/NixOS/nixpkgs/issues/240141
        map fetchurl (lib.attrValues muslPatches)
      )
      ++ lib.optionals stdenv'.hostPlatform.isLinux [
        ./patches/socketdir-in-run-13+.patch
      ]
      ++ lib.optionals (stdenv'.hostPlatform.isDarwin && olderThan "16") [
        ./patches/export-dynamic-darwin-15-.patch
      ];

      installTargets = [ "install-world" ];

      postPatch = ''
        substituteInPlace "src/Makefile.global.in" --subst-var out
        substituteInPlace "src/common/config_info.c" --subst-var dev
        cat ${./pg_config.env.mk} >> src/common/Makefile
      ''
      # This test always fails on hardware with >1 NUMA node: the sysfs
      # dirs providing information about the topology are hidden in the sandbox,
      # so postgres assumes there's only a single node `0`. However,
      # the test checks on which NUMA nodes the allocated pages are which is >1
      # on such hardware. This in turn triggers a safeguard in the view
      # which breaks the test.
      # Manual tests confirm that the testcase behaves properly outside of the
      # Nix sandbox.
      + lib.optionalString (atLeast "18") ''
        substituteInPlace src/test/regress/parallel_schedule \
          --replace-fail numa ""
      ''
      # This check was introduced upstream to prevent calls to "exit" inside libpq.
      # However, this doesn't work reliably with static linking, see this and following:
      # https://postgr.es/m/flat/20210703001639.GB2374652%40rfd.leadboat.com#52584ca4bd3cb9dac376f3158c419f97
      # Thus, disable the check entirely, as it would currently fail with this:
      # > libpq.so.5.17:                  U atexit
      # > libpq.so.5.17:                  U pthread_exit
      # > libpq must not be calling any function which invokes exit
      # Don't mind the fact that this checks libpq.**so** in pkgsStatic - that's correct, since PostgreSQL
      # still needs a shared library internally.
      + lib.optionalString (atLeast "15" && stdenv'.hostPlatform.isStatic) ''
        substituteInPlace src/interfaces/libpq/Makefile \
          --replace-fail "echo 'libpq must not be calling any function which invokes exit'; exit 1;" "echo;"
      '';

      postInstall = ''
        moveToOutput "bin/ecpg" "$dev"
        moveToOutput "lib/pgxs" "$dev"
      ''
      + lib.optionalString (stdenv'.buildPlatform.canExecute stdenv'.hostPlatform) ''
        mkdir -p "$dev/nix-support"
        "$out/bin/pg_config" > "$dev/nix-support/pg_config.expected"
      ''
      + ''
          rm "$out/bin/pg_config"
          make -C src/common pg_config.env
          substituteInPlace src/common/pg_config.env \
            --replace-fail "$out" "@out@" \
            --replace-fail "$man" "@man@"
          install -D src/common/pg_config.env "$dev/nix-support/pg_config.env"

        # postgres exposes external symbols get_pkginclude_path and similar. Those
        # can't be stripped away by --gc-sections/LTO, because they could theoretically
        # be used by dynamically loaded modules / extensions. To avoid circular dependencies,
        # references to -dev, -doc and -man are removed here. References to -lib must be kept,
        # because there is a realistic use-case for extensions to locate the /lib directory to
        # load other shared modules.
        remove-references-to -t "$dev" -t "$doc" -t "$man" "$out/bin/postgres"
      ''
      + lib.optionalString (!stdenv'.hostPlatform.isStatic) ''
        if [ -z "''${dontDisableStatic:-}" ]; then
          # Remove static libraries in case dynamic are available.
          for i in $lib/lib/*.a; do
            name="$(basename "$i")"
            ext="${stdenv'.hostPlatform.extensions.sharedLibrary}"
            if [ -e "$lib/lib/''${name%.a}$ext" ] || [ -e "''${i%.a}$ext" ]; then
              rm "$i"
            fi
          done
        fi
      ''
      + ''
        # The remaining static libraries are libpgcommon.a, libpgport.a and related.
        # Those are only used when building e.g. extensions, so go to $dev.
        moveToOutput "lib/*.a" "$dev"
      ''
      + lib.optionalString jitSupport ''
        # In the case of JIT support, prevent useless dependencies on header files
        find "$out/lib" -iname '*.bc' -type f -exec nuke-refs '{}' +

        # Stop lib depending on the -dev output of llvm
        remove-references-to -t ${llvmPackages.llvm.dev} "$out/lib/llvmjit${dlSuffix}"

        moveToOutput "lib/bitcode" "$jit"
        moveToOutput "lib/llvmjit*" "$jit"
      ''
      + lib.optionalString stdenv'.hostPlatform.isDarwin ''
        # The darwin specific Makefile for PGXS contains a reference to the postgres
        # binary. Some extensions (here: postgis), which are able to set bindir correctly
        # to their own output for installation, will then fail to find "postgres" during linking.
        substituteInPlace "$dev/lib/pgxs/src/Makefile.port" \
          --replace-fail '-bundle_loader $(bindir)/postgres' "-bundle_loader $out/bin/postgres"
      ''
      + lib.optionalString perlSupport ''
        moveToOutput "lib/*plperl*" "$plperl"
        moveToOutput "share/postgresql/extension/*plperl*" "$plperl"
      ''
      + lib.optionalString pythonSupport ''
        moveToOutput "lib/*plpython3*" "$plpython3"
        moveToOutput "share/postgresql/extension/*plpython3*" "$plpython3"
      ''
      + lib.optionalString tclSupport ''
        moveToOutput "lib/*pltcl*" "$pltcl"
        moveToOutput "share/postgresql/extension/*pltcl*" "$pltcl"
      '';

      postFixup = lib.optionalString stdenv'.hostPlatform.isGnu ''
        # initdb needs access to "locale" command from glibc.
        wrapProgram $out/bin/initdb --prefix PATH ":" ${glibc.bin}/bin
      '';

      # Running tests as "install check" to work around SIP issue on macOS:
      # https://www.postgresql.org/message-id/flat/4D8E1BC5-BBCF-4B19-8226-359201EA8305%40gmail.com
      # Also see <nixpkgs>/doc/stdenv/platform-notes.chapter.md
      doCheck = false;
      doInstallCheck =
        !(stdenv'.hostPlatform.isStatic)
        &&
          # Tests currently can't be run on darwin, because of a Nix bug:
          # https://github.com/NixOS/nix/issues/12548
          # https://git.lix.systems/lix-project/lix/issues/691
          # The error appears as this in the initdb logs:
          #   FATAL:  could not create shared memory segment: Cannot allocate memory
          # Don't let yourself be fooled when trying to remove this condition: Running
          # the tests works fine most of the time. But once the tests (or any package using
          # postgresqlTestHook) fails on the same machine for a few times, enough IPC objects
          # will be stuck around, and any future builds with the tests enabled *will* fail.
          !(stdenv'.hostPlatform.isDarwin)
        &&
          # Regression tests currently fail in pkgsMusl because of a difference in EXPLAIN output.
          !(stdenv'.hostPlatform.isMusl)
        &&
          # Modifying block sizes is expected to break regression tests.
          # https://www.postgresql.org/message-id/E1TJOeZ-000717-Lg%40wrigleys.postgresql.org
          (withBlocksize == null && withWalBlocksize == null);
      installCheckTarget = "check-world";

      passthru =
        let
          this = self.callPackage generic args;
        in
        {
          inherit dlSuffix;

          psqlSchema = lib.versions.major version;

          withJIT = if jitSupport then this.withPackages (_: [ this.jit ]) else null;
          withoutJIT = this;

          pkgs =
            let
              scope = {
                inherit
                  jitSupport
                  pythonSupport
                  perlSupport
                  tclSupport
                  ;
                inherit (llvmPackages) llvm;
                postgresql = this;
                stdenv = stdenv';
                postgresqlTestExtension = newSuper.callPackage ./postgresqlTestExtension.nix { };
                postgresqlBuildExtension = newSuper.callPackage ./postgresqlBuildExtension.nix { };
              };
              newSelf = self // scope;
              newSuper = {
                callPackage = newScope (scope // this.pkgs);
              };
            in
            import ./ext.nix newSelf newSuper;

          withPackages = postgresqlWithPackages {
            inherit buildEnv lib makeBinaryWrapper;
            postgresql = this;
          };

          pg_config = buildPackages.callPackage ./pg_config.nix {
            inherit (finalAttrs) finalPackage;
            outputs = {
              out = lib.getOutput "out" finalAttrs.finalPackage;
              man = lib.getOutput "man" finalAttrs.finalPackage;
            };
          };

          tests = {
            postgresql = nixosTests.postgresql.postgresql.passthru.override finalAttrs.finalPackage;
            postgresql-tls-client-cert = nixosTests.postgresql.postgresql-tls-client-cert.passthru.override finalAttrs.finalPackage;
            postgresql-wal-receiver = nixosTests.postgresql.postgresql-wal-receiver.passthru.override finalAttrs.finalPackage;
            pkg-config = testers.testMetaPkgConfig finalAttrs.finalPackage;
          }
          // lib.optionalAttrs jitSupport {
            postgresql-jit = nixosTests.postgresql.postgresql-jit.passthru.override finalAttrs.finalPackage;
          };
        };

      meta = with lib; {
        homepage = "https://www.postgresql.org";
        description = "Powerful, open source object-relational database system";
        license = licenses.postgresql;
        changelog = "https://www.postgresql.org/docs/release/${finalAttrs.version}/";
        teams = [ teams.postgres ];
        pkgConfigModules = [
          "libecpg"
          "libecpg_compat"
          "libpgtypes"
          "libpq"
        ];
        platforms = platforms.unix;

        # JIT support doesn't work with cross-compilation. It is attempted to build LLVM-bytecode
        # (`%.bc` is the corresponding `make(1)`-rule) for each sub-directory in `backend/` for
        # the JIT apparently, but with a $(CLANG) that can produce binaries for the build, not the
        # host-platform.
        #
        # I managed to get a cross-build with JIT support working with
        # `depsBuildBuild = [ llvmPackages.clang ] ++ buildInputs`, but considering that the
        # resulting LLVM IR isn't platform-independent this doesn't give you much.
        # In fact, I tried to test the result in a VM-test, but as soon as JIT was used to optimize
        # a query, postgres would coredump with `Illegal instruction`.
        #
        # Note: This is "host canExecute build" on purpose, since this is about the LLVM that is called
        # to do JIT at **runtime**.
        broken = jitSupport && !stdenv.hostPlatform.canExecute stdenv.buildPlatform;
      };
    });

  postgresqlWithPackages =
    {
      postgresql,
      buildEnv,
      lib,
      makeBinaryWrapper,
    }:
    f:
    let
      installedExtensions = f postgresql.pkgs;
      finalPackage = buildEnv {
        name = "${postgresql.pname}-and-plugins-${postgresql.version}";
        paths = installedExtensions ++ [
          # consider keeping in-sync with `postBuild` below
          postgresql
          postgresql.man # in case user installs this into environment
        ];

        pathsToLink = [
          "/"
          "/bin"
          "/share/postgresql/extension"
          # Unbreaks Omnigres' build system
          "/share/postgresql/timezonesets"
          "/share/postgresql/tsearch_data"
        ];

        nativeBuildInputs = [ makeBinaryWrapper ];
        postBuild =
          let
            args = lib.concatMap (ext: ext.wrapperArgs or [ ]) installedExtensions;
          in
          ''
            wrapProgram "$out/bin/postgres" ${lib.concatStringsSep " " args}
          '';

        passthru = {
          inherit installedExtensions;
          inherit (postgresql)
            pkgs
            psqlSchema
            version
            ;

          pg_config = postgresql.pg_config.override {
            outputs = {
              out = finalPackage;
              man = finalPackage;
            };
          };

          withJIT = postgresqlWithPackages {
            inherit
              buildEnv
              lib
              makeBinaryWrapper
              postgresql
              ;
          } (_: installedExtensions ++ [ postgresql.jit ]);
          withoutJIT = postgresqlWithPackages {
            inherit
              buildEnv
              lib
              makeBinaryWrapper
              postgresql
              ;
          } (_: lib.remove postgresql.jit installedExtensions);

          withPackages =
            f':
            postgresqlWithPackages {
              inherit
                buildEnv
                lib
                makeBinaryWrapper
                postgresql
                ;
            } (ps: installedExtensions ++ f' ps);
        };
      };
    in
    finalPackage;

in
# passed by <major>.nix
versionArgs:
# passed by default.nix
{ self, ... }@defaultArgs:
self.callPackage generic (defaultArgs // versionArgs)
